package com.lt.lumentracks.interceptor;


import cn.hutool.json.JSONUtil;
import com.lt.lumentracks.constant.JwtClaimsConstant;
import com.lt.lumentracks.constant.MvcConstant;
import com.lt.lumentracks.context.BaseContext;
import com.lt.lumentracks.entity.vo.common.Result;
import com.lt.lumentracks.utils.jwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;


//检查是否登陆的拦截器--用户端
@Slf4j
@Component
public class LoginCheckInterceptor_client implements HandlerInterceptor {

    @Override //目标资源方法运行前运行，返回true则放行，返回false则不放行
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {

        /*
          当一个 HTTP 请求到达 Spring MVC 应用时：
          1、DispatcherServlet接收请求
          2、HandlerMapping尝试为请求找到匹配的Handler（通常是一个Controller方法）
          3、HandlerAdapter负责调用找到的Handler
          4、Interceptor在Handler执行前后被触发（重点！！！）
         */
        // 检查handler是否为Controller方法，避免拦截静态资源或不存在的路径
        if (!(handler instanceof HandlerMethod)) {
            return true; // 放行非Controller请求（如404、请求静态资源等），因为不需要对这些请求进行业务拦截，直接返回原本的信息就行
        }

        //1.获取【请求头】中的令牌
        String jwt = req.getHeader(MvcConstant.LOGIN_TOKEN_NAME);

        //2.判断令牌是否存在，如果不存在，返回错误结果
        if ( !StringUtils.hasLength(jwt) ) {
            log.info("令牌不存在，当前请求的url：{}", req.getRequestURI());
            Result<Object> err = Result.error(MvcConstant.NOT_LOGIN_INFO); // 编写返回信息

            //手动转换 对象-->Json,
            String notLogin = JSONUtil.toJsonStr(err);
            resp.getWriter().write(notLogin);
            return false;
        }

        //3.解析令牌，如果解析失败，则返回错误结果
        try {
            Claims claims = jwtUtils.ParseJwt(jwt);
            Integer userId = Integer.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
            BaseContext.setCurrentId(userId); //使用ThreadLocal把当前【正在操作的用户的id】缓存在【当前线程】中
        }
        catch (Exception e) { //jwt解析失败
            log.info("令牌解析失败，当前请求的url：{}", req.getRequestURI());
            Result<Object> err = Result.error(MvcConstant.NOT_LOGIN_INFO); // 编写返回信息

            //手动转换 对象-->Json
            String notLogin = JSONUtil.toJsonStr(err);
            resp.getWriter().write(notLogin);
            return false;
        }

        //4.令牌合法，放行
        return true;

    }

    @Override //目标资源方法运行后运行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        //System.out.println("2.用户登录拦截器中的postHandle方法...");
    }

    @Override //视图渲染完毕后运行，最后运行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //System.out.println("3.用户登录拦截器中的afterCompletion方法...");
        BaseContext.removeCurrentId(); // 线程变量销毁，防止内存泄漏
    }
}
